#ifndef MINI_BASIC_ENVIRONMENT_H
#define MINI_BASIC_ENVIRONMENT_H

#pragma once

#include "stdafx.h"
#include <vector>
#include <map>
#include <stack>
#include <vector>
#include "../Parser/Vals.h"
#include "Variable.h"
#include "ForLoop.h"
#include "MemoryArea.h"
#include "ConsoleManager.h"

typedef struct _ExecutionParameters ExecutionParameters;

namespace MiniBasic
{
    class Lexecutioner;

    class Environment
    {
    public:
        static const mbint PADDING_CHANGED_TAG = 1 << 31;
        Environment(ExecutionParameters* pExParams);

        HRESULT DoExecution(Lexecutioner& lex);

        // variables
        Variable* GetArrayVar(mbint location);
        Variable* GetLetterVar(char letter);

        // print padding
        void SetPadding(mbint spaces);
        mbint GetPadding() const;
        void ResetPadding();

        // for loops
        //bool GetCurrentFor(ForLoop& current) const;
        void ExitFor();
        bool EnterForLoop(Lexecutioner* lex, const var_type& v1, const var_type& v2, mbint step = 1);
        int EvaluateTopFor(Lexecutioner* lex, Variable* var = 0) const;

        // GoSubs
        bool EnterSub(Lexecutioner* lex, mbint line);
        bool ExitSub(Lexecutioner* lex);

        // i/o statements
        bool DoInput(const var_type& v1, mbint currentLine);
        void DoOutput(const std::string& outStr) const;
        
        // accessors
        inline MemoryArea& GetUserMemoryArea() {return userMemory;}
        inline ConsoleManager& GetConsole() {return conManager;}

    private:
        int printNumberPadding;
        std::vector<ForLoop> forStack;
        std::stack<ULONG_PTR> gosubStack;
        std::map<mbint, Variable> arrayVariables;
        std::vector<Variable> singleLetterVariables;
        //std::auto_ptr<Lexecutioner> lex;
        MemoryArea userMemory;
        ConsoleManager conManager;
    };
}

#endif
